package yxy.apple.util;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.Set;

import org.reflections.Reflections;
import org.reflections.scanners.MethodAnnotationsScanner;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.scanners.TypeAnnotationsScanner;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;

public class ReflectionUtility {

	private static Reflections getReflections(String packageName) {
		Collection<URL> urls = ClasspathHelper.forPackage(packageName);
		URL[] url = new URL[urls.size()];
		url = urls.toArray(url);
		URLClassLoader classLoader = new URLClassLoader(url);
		ConfigurationBuilder configBuilder = new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage(packageName))//
				.setScanners(new SubTypesScanner(), //
						new TypeAnnotationsScanner(), //
//		        	new MethodParameterScanner(), 
						new MethodAnnotationsScanner()// ,
//		        	new FieldAnnotationsScanner()
				).addClassLoader(classLoader);
		Reflections reflections = new Reflections(configBuilder);
		return reflections;
	}

	public static <T> Set<Class<? extends T>> getSubTypesOf(String packageName, Class<T> type) {
		Reflections reflections = getReflections(packageName);
		return reflections.getSubTypesOf(type);
	}

	public static Set<Class<?>> getTypesAnnotatedWith(String packageName, Class<? extends Annotation> annotation) {
		Reflections reflections = getReflections(packageName);
		return reflections.getTypesAnnotatedWith(annotation);
	}

	public static Set<Method> getMethodsAnnotatedWith(String packageName, Class<? extends Annotation> annotation) {
		Reflections reflections = getReflections(packageName);
		return reflections.getMethodsAnnotatedWith(annotation);
	}
}
